#include <iostream>
#include <fstream>
#include <thread>
#include <atomic>
#include <string>
#include <chrono>
#include <vector>
#include <sstream>
#include <regex>

// OpenCV
#include <opencv2/opencv.hpp>

// FFmpeg (需要用 extern "C" 包裹)
extern "C" {
// 使用更通用的FFmpeg头文件路径
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/avutil.h>
}

// PJSIP
#include <pjsua2/endpoint.hpp>
#include <pjsua2/account.hpp>
#include <pjsua2/call.hpp>
#include <pjsua-lib/pjsua.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_msg.h>
#include <pjsip/sip_uri.h>
#include <pjsip/sip_transaction.h>

// 项目头文件
#include "src/SipManager.h"
#include "src/StreamManager.h"
#include "src/Logger.h"
#include "src/Config.h"

using namespace std;

// 全局变量
std::atomic<bool> g_running(true);
string g_stream_ip = "127.0.0.1";    // 推流目标IP
int g_stream_port = 1935;            // 推流目标端口
string g_stream_transport = "TCP";   // 推流传输协议
string g_stream_setup = "passive";   // 连接模式
string g_stream_ssrc = "";           // SSRC流标识
pjsua_acc_id g_acc_id = PJSUA_INVALID_ID; // 全局账户ID

// 设备和通道配置信息 - 使用常量方便管理
const string DEVICE_ID = "34020000001320000002";  // 设备ID
const string CHANNEL_ID = "34020000001320000003"; // 通道ID - 不同于设备ID
const string DEVICE_NAME = "V5摄像头";
const string MANUFACTURER = "V5";
const string MODEL = "V5-Camera";
const string FIRMWARE = "1.0.0";
const string PASSWORD = "12345678";
const string REALM = "4101050000";
const string SERVER_IP = "47.120.9.38";
const int SERVER_PORT = 8116;
const string PUBLIC_IP = "47.120.9.38";
const string SERVER_ID = "41010500002000000001";

// 获取当前日期时间
string getCurrentTime() {
    auto now = chrono::system_clock::now();
    auto now_c = chrono::system_clock::to_time_t(now);
    char time_buf[64];
    strftime(time_buf, sizeof(time_buf), "%Y-%m-%dT%H:%M:%S", localtime(&now_c));
    return string(time_buf);
}

// 获取当前日期
string getCurrentDate() {
    auto now = chrono::system_clock::now();
    auto now_c = chrono::system_clock::to_time_t(now);
    char time_buf[64];
    strftime(time_buf, sizeof(time_buf), "%Y-%m-%d", localtime(&now_c));
    return string(time_buf);
}

// 函数前向声明
void log(const string& message);
string extractXmlValue(const string& xml, const string& tag);
string generateCatalogResponse(const string& sn);
string generateDeviceStatusResponse(const string& sn);
string generateDeviceInfoResponse(const string& sn);
string generatePTZResponse(const string& sn, bool success = true);
string generateRecordInfoResponse(const string& sn);
void sendSipMessage(pjsua_acc_id acc_id, const string& target_uri, const string& content, const string& content_type = "Application/MANSCDP+xml");
void streamingThread();
void on_reg_state(pjsua_acc_id acc_id);
void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata);
void on_call_state(pjsua_call_id call_id, pjsip_event *e);
void on_call_media_state(pjsua_call_id call_id);
pj_bool_t on_rx_request(pjsip_rx_data *rdata);

// 类前向声明
class MyCall;
class MyAccount;

// 日志函数
void log(const string& message) {
    auto now = chrono::system_clock::now();
    auto now_c = chrono::system_clock::to_time_t(now);
    char time_buf[64];
    strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", localtime(&now_c));
    cout << time_buf << " " << message << endl;
    // 确保日志立即输出
    cout.flush();
}

// 从XML内容中提取指定标签的值
string extractXmlValue(const string& xml, const string& tag) {
    regex pattern("<" + tag + ">(.*?)</" + tag + ">");
    smatch match;
    if (regex_search(xml, match, pattern) && match.size() > 1) {
        return match[1].str();
    }
    return "";
}

// 生成Catalog响应内容
string generateCatalogResponse(const string& sn) {
    stringstream ss;
    ss << "<?xml version=\"1.0\" encoding=\"GB2312\"?>" << endl
       << "<Response>" << endl
       << "  <CmdType>Catalog</CmdType>" << endl
       << "  <SN>" << sn << "</SN>" << endl
       << "  <DeviceID>" << DEVICE_ID << "</DeviceID>" << endl
       << "  <SumNum>1</SumNum>" << endl
       << "  <DeviceList Num=\"1\">" << endl
       << "    <Item>" << endl
       << "      <DeviceID>" << CHANNEL_ID << "</DeviceID>" << endl
       << "      <Name>V5摄像头通道1</Name>" << endl
       << "      <Manufacturer>" << MANUFACTURER << "</Manufacturer>" << endl
       << "      <Model>" << MODEL << "</Model>" << endl
       << "      <Owner>V5</Owner>" << endl
       << "      <CivilCode>" << REALM << "</CivilCode>" << endl
       << "      <Address>本地测试地址</Address>" << endl
       << "      <Parental>0</Parental>" << endl
       << "      <ParentID>" << DEVICE_ID << "</ParentID>" << endl
       << "      <SafetyWay>0</SafetyWay>" << endl
       << "      <RegisterWay>1</RegisterWay>" << endl
       << "      <Secrecy>0</Secrecy>" << endl
       << "      <Status>ON</Status>" << endl
       << "    </Item>" << endl
       << "  </DeviceList>" << endl
       << "</Response>";
    return ss.str();
}

// 生成设备状态响应内容
string generateDeviceStatusResponse(const string& sn) {
    stringstream ss;
    ss << "<?xml version=\"1.0\" encoding=\"GB2312\"?>" << endl
       << "<Response>" << endl
       << "  <CmdType>DeviceStatus</CmdType>" << endl
       << "  <SN>" << sn << "</SN>" << endl
       << "  <DeviceID>" << DEVICE_ID << "</DeviceID>" << endl
       << "  <Result>OK</Result>" << endl
       << "  <Online>ONLINE</Online>" << endl
       << "  <Status>OK</Status>" << endl
       << "  <DeviceTime>" << getCurrentTime() << "</DeviceTime>" << endl
       << "  <Alarmstatus>0</Alarmstatus>" << endl
       << "</Response>";
    return ss.str();
}

// 生成设备信息响应内容
string generateDeviceInfoResponse(const string& sn) {
    stringstream ss;
    ss << "<?xml version=\"1.0\" encoding=\"GB2312\"?>" << endl
       << "<Response>" << endl
       << "  <CmdType>DeviceInfo</CmdType>" << endl
       << "  <SN>" << sn << "</SN>" << endl
       << "  <DeviceID>" << DEVICE_ID << "</DeviceID>" << endl
       << "  <Result>OK</Result>" << endl
       << "  <DeviceName>" << DEVICE_NAME << "</DeviceName>" << endl
       << "  <Manufacturer>" << MANUFACTURER << "</Manufacturer>" << endl
       << "  <Model>" << MODEL << "</Model>" << endl
       << "  <Firmware>" << FIRMWARE << "</Firmware>" << endl
       << "  <Channel>1</Channel>" << endl
       << "  <SIMNum></SIMNum>" << endl
       << "</Response>";
    return ss.str();
}

// 生成PTZ控制响应内容
string generatePTZResponse(const string& sn, bool success) {
    stringstream ss;
    ss << "<?xml version=\"1.0\" encoding=\"GB2312\"?>" << endl
       << "<Response>" << endl
       << "  <CmdType>PTZCmd</CmdType>" << endl
       << "  <SN>" << sn << "</SN>" << endl
       << "  <DeviceID>" << CHANNEL_ID << "</DeviceID>" << endl
       << "  <Result>" << (success ? "OK" : "ERROR") << "</Result>" << endl
       << "</Response>";
    return ss.str();
}

// 生成录像文件列表响应
string generateRecordInfoResponse(const string& sn) {
    // 生成一个示例录像列表，实际应用中应从存储中读取
    string currentDate = getCurrentDate();
    string startTime = currentDate + "T00:00:00";
    string endTime = currentDate + "T00:10:00";
    
    stringstream ss;
    ss << "<?xml version=\"1.0\" encoding=\"GB2312\"?>" << endl
       << "<Response>" << endl
       << "  <CmdType>RecordInfo</CmdType>" << endl
       << "  <SN>" << sn << "</SN>" << endl
       << "  <DeviceID>" << CHANNEL_ID << "</DeviceID>" << endl
       << "  <SumNum>1</SumNum>" << endl
       << "  <RecordList Num=\"1\">" << endl
       << "    <Item>" << endl
       << "      <DeviceID>" << CHANNEL_ID << "</DeviceID>" << endl
       << "      <Name>录像1</Name>" << endl
       << "      <StartTime>" << startTime << "</StartTime>" << endl
       << "      <EndTime>" << endTime << "</EndTime>" << endl
       << "      <Secrecy>0</Secrecy>" << endl
       << "      <Type>time</Type>" << endl
       << "      <FileSize>10240</FileSize>" << endl
       << "    </Item>" << endl
       << "  </RecordList>" << endl
       << "</Response>";
    return ss.str();
}

// 使用PJSIP C接口发送SIP MESSAGE
void sendSipMessage(pjsua_acc_id acc_id, const string& target_uri, const string& content, const string& content_type) {
    // 将C++字符串转换为PJSIP字符串
    pj_str_t to_uri = pj_str((char*)target_uri.c_str());
    pj_str_t content_str = pj_str((char*)content.c_str());
    
    // 准备消息数据
    pjsua_msg_data msg_data;
    pjsua_msg_data_init(&msg_data);
    
    // 设置消息头部和内容类型
    char content_type_buf[128];
    snprintf(content_type_buf, sizeof(content_type_buf), "%s", content_type.c_str());
    msg_data.content_type = pj_str(content_type_buf);
    
    // 发送即时消息
    pj_status_t status = pjsua_im_send(acc_id, &to_uri, NULL, &content_str, &msg_data, NULL);
    
    if (status != PJ_SUCCESS) {
        char errmsg[PJ_ERR_MSG_SIZE];
        pj_strerror(status, errmsg, sizeof(errmsg));
        log("发送消息失败，错误: " + string(errmsg));
    } else {
        log("消息已发送");
    }
}

void streamingThread() {
    log("启动视频推流线程");
    
    // 等待一小段时间，确保呼叫已完全建立
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    
    // 硬编码视频文件路径
    string video_path = "test.mp4";
    
    // 检查文件是否存在
    std::ifstream f(video_path.c_str());
    if (!f.good()) {
        log("错误: 测试视频文件 " + video_path + " 不存在!");
        // 尝试使用绝对路径
        char current_path[FILENAME_MAX];
        if (getcwd(current_path, sizeof(current_path))) {
            log("当前工作目录: " + string(current_path));
            log("尝试在当前目录查找测试视频...");
            string cmd = "ls -la";
            system(cmd.c_str());
        }
        return;
    }
    f.close();
    
    log("找到测试视频文件: " + video_path);
    
    // 根据媒体协商结果构造FFmpeg命令
    string ffmpeg_cmd;
    
    // 选择合适的推流参数
    if (g_stream_transport == "TCP") {
        if (g_stream_setup == "active") {
            // 主动模式 - 我们作为客户端连接到服务器
            ffmpeg_cmd = string("ffmpeg -y -re -i ") + video_path + 
                         string(" -c:v copy -an") +  // 只复制视频流，不要音频
                         string(" -f rtp_mpegts rtp://") + g_stream_ip + string(":") + to_string(g_stream_port) + 
                         string("?rtcpport=") + to_string(g_stream_port) +
                         string("&pkt_size=1316") +
                         string("&ssrc=") + g_stream_ssrc +
                         string("&transport=tcp");
                         
            log("使用TCP主动模式推流: " + ffmpeg_cmd);
        } else {
            // 被动模式 - 我们作为服务器监听
            ffmpeg_cmd = string("ffmpeg -y -re -i ") + video_path + 
                         string(" -c:v copy -an") +  // 只复制视频流，不要音频
                         string(" -f rtp_mpegts rtp://0.0.0.0:5000") + 
                         string("?rtcpport=5001") +
                         string("&pkt_size=1316") +
                         string("&ssrc=") + g_stream_ssrc +
                         string("&transport=tcp") +
                         string("&listen=1");
                         
            log("使用TCP被动模式推流: " + ffmpeg_cmd);
        }
    } else {
        // UDP模式
        ffmpeg_cmd = string("ffmpeg -y -re -i ") + video_path + 
                     string(" -c:v copy -an") +  // 只复制视频流，不要音频
                     string(" -f rtp_mpegts rtp://") + g_stream_ip + string(":") + to_string(g_stream_port) + 
                     string("?rtcpport=") + to_string(g_stream_port) +
                     string("&pkt_size=1316") +
                     string("&ssrc=") + g_stream_ssrc;
                     
        log("使用UDP模式推流: " + ffmpeg_cmd);
    }
    
    // 执行FFmpeg命令
    log("开始执行FFmpeg推流: " + ffmpeg_cmd);
    FILE* pipe = popen(ffmpeg_cmd.c_str(), "r");
    
    if (!pipe) {
        log("无法启动FFmpeg推流，请确认FFmpeg已安装");
        // 尝试检查FFmpeg是否安装
        system("which ffmpeg");
        return;
    }
    
    log("FFmpeg推流已启动");
    
    // 不阻塞主线程，读取并记录FFmpeg输出
    char buffer[512];
    while (g_running && fgets(buffer, sizeof(buffer), pipe) != NULL) {
        // 删除末尾的换行符
        buffer[strcspn(buffer, "\n")] = 0;
        // 记录所有输出以便调试
        log("FFmpeg: " + string(buffer));
    }
    
    // 关闭管道
    pclose(pipe);
    log("推流线程退出");
}

// 注册状态回调
void on_reg_state(pjsua_acc_id acc_id) {
    pjsua_acc_info info;
    pjsua_acc_get_info(acc_id, &info);
    
    if (info.status == 200 || info.status == 0) {
        log("SIP注册成功");
    } else {
        log("SIP注册失败或注销，状态码: " + std::to_string(info.status));
    }
}

// 呼叫状态回调
void on_call_state(pjsua_call_id call_id, pjsip_event *e) {
    pjsua_call_info ci;
    pjsua_call_get_info(call_id, &ci);
    
    // 打印呼叫状态
    char state_str[100];
    pj_ansi_snprintf(state_str, sizeof(state_str), "%.*s", (int)ci.state_text.slen, ci.state_text.ptr);
    log("呼叫状态: " + std::string(state_str));
    
    // 检查是否断开连接
    if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
        log("呼叫已断开");
        // 停止推流线程
        g_running = false;
    }
}

// 媒体状态回调
void on_call_media_state(pjsua_call_id call_id) {
    log("媒体状态改变");
}

// 处理传入呼叫
void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) {
    log("收到呼叫请求 ID: " + std::to_string(call_id) + " 账户ID: " + std::to_string(acc_id));
    
    // 使用SipManager处理呼叫
    bool success = SipManager::getInstance().handleIncomingCall(acc_id, call_id, rdata);
    
    if (!success) {
        log("SipManager处理呼叫失败，尝试拒绝呼叫...");
        try {
            // 拒绝呼叫，响应码488表示媒体不兼容
            pjsua_call_hangup(call_id, 488, NULL, NULL);
        } catch (...) {
            log("拒绝呼叫时出现异常");
        }
    }
}

// 接收SIP MESSAGE请求的处理函数
pj_bool_t on_rx_request(pjsip_rx_data *rdata) {
    // 检查是否是MESSAGE请求
    const pj_str_t message_method = pj_str((char*)"MESSAGE");
    if (pj_strcmp(&rdata->msg_info.msg->line.req.method.name, &message_method) == 0) {
        // 获取消息体
        if (rdata->msg_info.msg->body) {
            // 提取消息内容
            std::string message_body((char*)rdata->msg_info.msg->body->data, rdata->msg_info.msg->body->len);
            log("收到MESSAGE消息: " + message_body);
            
            // 提取消息类型
            string cmdType = extractXmlValue(message_body, "CmdType");
            string sn = extractXmlValue(message_body, "SN");
            string deviceId = extractXmlValue(message_body, "DeviceID");
            
            log("命令类型: " + cmdType + ", SN: " + sn + ", 目标设备: " + deviceId);
            
            // 构建目标URI（服务器的URI）- 使用完整的服务器URI，包括IP和端口
            string target_uri = "sip:" + SERVER_ID + "@" + SERVER_IP + ":" + to_string(SERVER_PORT);
            log("发送响应到: " + target_uri);
            
            // 根据命令类型生成相应的响应
            string response;
            
            // 处理Catalog请求 - 设备通道列表
            if (cmdType == "Catalog") {
                response = generateCatalogResponse(sn);
                log("准备发送Catalog响应");
                sendSipMessage(g_acc_id, target_uri, response, "Application/MANSCDP+xml");
            }
            // 处理DeviceStatus请求 - 设备状态
            else if (cmdType == "DeviceStatus") {
                response = generateDeviceStatusResponse(sn);
                log("准备发送DeviceStatus响应");
                sendSipMessage(g_acc_id, target_uri, response, "Application/MANSCDP+xml");
            }
            // 处理DeviceInfo请求 - 设备信息
            else if (cmdType == "DeviceInfo") {
                response = generateDeviceInfoResponse(sn);
                log("准备发送DeviceInfo响应");
                sendSipMessage(g_acc_id, target_uri, response, "Application/MANSCDP+xml");
            }
            // 处理PTZ控制请求
            else if (cmdType == "PTZCmd") {
                // 处理PTZ控制，这里只是简单记录，实际应用中需要控制摄像头
                string ptzCmd = extractXmlValue(message_body, "PTZCmd");
                log("收到PTZ控制命令: " + ptzCmd);
                
                // 回复PTZ控制响应
                response = generatePTZResponse(sn, true);
                sendSipMessage(g_acc_id, target_uri, response, "Application/MANSCDP+xml");
            }
            // 处理录像查询请求
            else if (cmdType == "RecordInfo") {
                log("收到录像查询请求");
                response = generateRecordInfoResponse(sn);
                sendSipMessage(g_acc_id, target_uri, response, "Application/MANSCDP+xml");
            }
            // 其他命令类型
            else {
                log("收到未处理的命令类型: " + cmdType);
            }
            
            // 回复200 OK
            pjsip_endpt_respond_stateless(pjsua_get_pjsip_endpt(), rdata, 200, NULL, NULL, NULL);
            return PJ_TRUE;
        }
    }
    
    // 返回PJ_FALSE表示未处理，继续传递给其他模块
    return PJ_FALSE;
}

// 测试SDP解析函数，用于调试
void testSdpParsing() {
    log("执行SDP解析测试");
    
    // 测试用的SDP，基于实际请求中的SDP格式
    string test_sdp = 
        "v=0\r\n"
        "o=34020000001320000002 0 0 IN IP4 47.120.9.38\r\n"
        "s=Play\r\n"
        "c=IN IP4 47.120.9.38\r\n"
        "t=0 0\r\n"
        "m=video 30490 TCP/RTP/AVP 96 97 98 99\r\n"
        "a=recvonly\r\n"
        "a=rtpmap:96 PS/90000\r\n"
        "a=rtpmap:98 H264/90000\r\n"
        "a=rtpmap:97 MPEG4/90000\r\n"
        "a=rtpmap:99 H265/90000\r\n"
        "a=setup:passive\r\n"
        "a=connection:new\r\n"
        "y=0105002129\r\n";
        
    log("测试SDP:\n" + test_sdp);
    
    // 提取媒体参数
    string remote_ip;
    int remote_port = 0;
    string ssrc;
    string transport_mode = "UDP"; // 默认是UDP
    string setup_mode = "passive"; // 默认是被动模式

    // 提取目标IP地址
    size_t c_pos = test_sdp.find("c=IN IP4 ");
    if (c_pos != string::npos) {
        remote_ip = test_sdp.substr(c_pos + 9);
        remote_ip = remote_ip.substr(0, remote_ip.find("\r\n"));
        log("提取到对端IP: " + remote_ip);
    } else {
        log("错误: 未找到c=行");
    }

    // 提取媒体端口
    size_t m_pos = test_sdp.find("m=video ");
    if (m_pos != string::npos) {
        string portStr = test_sdp.substr(m_pos + 8);
        remote_port = stoi(portStr.substr(0, portStr.find(" ")));
        log("提取到对端端口: " + to_string(remote_port));
    } else {
        log("错误: 未找到m=video行");
    }

    // 提取SSRC
    size_t y_pos = test_sdp.find("y=");
    if (y_pos != string::npos) {
        ssrc = test_sdp.substr(y_pos + 2);
        ssrc = ssrc.substr(0, ssrc.find("\r\n"));
        log("提取到SSRC: " + ssrc);
    } else {
        log("错误: 未找到y=行");
    }

    // 判断传输协议
    if (test_sdp.find("TCP/RTP/AVP") != string::npos) {
        transport_mode = "TCP";
        log("使用TCP传输");

        // 检查a=setup行来确定TCP连接模式
        size_t setup_pos = test_sdp.find("a=setup:");
        if (setup_pos != string::npos) {
            string setup_value = test_sdp.substr(setup_pos + 8);
            setup_value = setup_value.substr(0, setup_value.find("\r\n"));
            if (setup_value == "active") {
                setup_mode = "passive"; // 如果对方是active，我们就是passive
            } else if (setup_value == "passive") {
                setup_mode = "active"; // 如果对方是passive，我们就是active
            }
            log("设置连接模式: " + setup_mode);
        } else {
            log("未找到a=setup行，默认使用被动模式");
        }
    } else {
        log("使用UDP传输");
    }
    
    // 检查解析结果是否完整
    if (remote_ip.empty() || remote_port == 0 || ssrc.empty()) {
        log("警告: SDP解析不完整，某些关键信息缺失");
    }
    
    // 测试SDP应答生成
    string sdp_answer;
    sdp_answer = "v=0\r\n";
    sdp_answer += "o=" + DEVICE_ID + " 0 0 IN IP4 " + PUBLIC_IP + "\r\n";
    sdp_answer += "s=Play\r\n";
    sdp_answer += "c=IN IP4 " + PUBLIC_IP + "\r\n";
    sdp_answer += "t=0 0\r\n";
    
    if (transport_mode == "TCP") {
        if (setup_mode == "active") {
            // 主动模式
            sdp_answer += "m=video 9 TCP/RTP/AVP 96 97 98 99\r\n";
            sdp_answer += "a=setup:active\r\n";
            sdp_answer += "a=connection:new\r\n";
        } else {
            // 被动模式
            sdp_answer += "m=video 5000 TCP/RTP/AVP 96 97 98 99\r\n";
            sdp_answer += "a=setup:passive\r\n";
            sdp_answer += "a=connection:new\r\n";
        }
    } else {
        // UDP模式
        sdp_answer += "m=video 5000 RTP/AVP 96 97 98 99\r\n";
    }
    
    sdp_answer += "a=sendonly\r\n";
    sdp_answer += "a=rtpmap:96 PS/90000\r\n";
    sdp_answer += "a=rtpmap:98 H264/90000\r\n";
    sdp_answer += "a=rtpmap:97 MPEG4/90000\r\n";
    sdp_answer += "a=rtpmap:99 H265/90000\r\n";
    sdp_answer += "y=" + ssrc + "\r\n";
    
    log("生成的SDP应答:\n" + sdp_answer);
    
    // 测试ffmpeg命令生成
    string ffmpeg_cmd;
    if (transport_mode == "TCP") {
        if (setup_mode == "active") {
            // 主动模式 - 我们作为客户端连接到服务器
            ffmpeg_cmd = string("ffmpeg -y -re -i test.mp4") + 
                        string(" -c:v copy -an") + 
                        string(" -f rtp_mpegts rtp://") + remote_ip + string(":") + to_string(remote_port) + 
                        string("?rtcpport=") + to_string(remote_port) +
                        string("&pkt_size=1316") +
                        string("&ssrc=") + ssrc +
                        string("&transport=tcp");
                        
            log("TCP主动模式命令: " + ffmpeg_cmd);
        } else {
            // 被动模式 - 我们作为服务器监听
            ffmpeg_cmd = string("ffmpeg -y -re -i test.mp4") + 
                        string(" -c:v copy -an") + 
                        string(" -f rtp_mpegts rtp://0.0.0.0:5000") + 
                        string("?rtcpport=5001") +
                        string("&pkt_size=1316") +
                        string("&ssrc=") + ssrc +
                        string("&transport=tcp") +
                        string("&listen=1");
                        
            log("TCP被动模式命令: " + ffmpeg_cmd);
        }
    } else {
        // UDP模式
        ffmpeg_cmd = string("ffmpeg -y -re -i test.mp4") + 
                    string(" -c:v copy -an") + 
                    string(" -f rtp_mpegts rtp://") + remote_ip + string(":") + to_string(remote_port) + 
                    string("?rtcpport=") + to_string(remote_port) +
                    string("&pkt_size=1316") +
                    string("&ssrc=") + ssrc;
                    
        log("UDP模式命令: " + ffmpeg_cmd);
    }
    
    log("FFmpeg命令行格式正确性检查...");
    
    // 实际的参数命令检查应当通过运行ffmpeg -h查看
    if (ffmpeg_cmd.find("-re") != string::npos && 
        ffmpeg_cmd.find("-i test.mp4") != string::npos && 
        ffmpeg_cmd.find("-f rtp_mpegts") != string::npos) {
        log("FFmpeg命令基本参数检查通过");
    } else {
        log("警告: FFmpeg命令格式可能有问题");
    }
    
    log("SDP解析测试完成");
}

int main(int argc, char* argv[]) {
    cout << "=====================================" << endl;
    cout << "GB28181客户端 - V5摄像头硬编码版启动" << endl;
    cout << "=====================================" << endl;
    
    log("GB28181客户端 - V5摄像头版本启动");
    log("使用硬编码配置");
    log("若需修改配置，请编辑源代码中的Config类");
    
    try {
        // 初始化SIP栈
        if (!SipManager::getInstance().initialize()) {
            log("无法初始化SIP栈");
            return -1;
        }
        
        // 注册到服务器
        if (!SipManager::getInstance().registerToServer()) {
            log("无法注册到SIP服务器");
            return -1;
        }
        
        // 解析SDP测试
        log("执行SDP解析测试");
        std::string test_sdp = 
            "v=0\r\n"
            "o=34020000001320000002 0 0 IN IP4 47.120.9.38\r\n"
            "s=Play\r\n"
            "c=IN IP4 47.120.9.38\r\n"
            "t=0 0\r\n"
            "m=video 30490 TCP/RTP/AVP 96 97 98 99\r\n"
            "a=recvonly\r\n"
            "a=rtpmap:96 PS/90000\r\n"
            "a=rtpmap:98 H264/90000\r\n"
            "a=rtpmap:97 MPEG4/90000\r\n"
            "a=rtpmap:99 H265/90000\r\n"
            "a=setup:passive\r\n"
            "a=connection:new\r\n"
            "y=0105002129\r\n";
        
        // 解析SDP
        SdpInfo sdp_info = StreamManager::getInstance().parseSdp(test_sdp);
        
        // 生成SDP应答
        std::string sdp_answer = StreamManager::getInstance().generateSdpAnswer(sdp_info);
        log("生成SDP应答:\n" + sdp_answer);
        
        // 测试生成FFmpeg命令
        log("使用" + sdp_info.transport + (sdp_info.setup == "active" ? "主动" : "被动") + "模式推流");
        
        log("应用程序初始化成功");
        log("GB28181客户端运行中，等待平台的点播请求...");
        log("按Ctrl+C退出程序");
        
        // 等待用户输入退出
        while(true) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        
    } catch (pj::Error& err) {
        log("PJSIP错误: " + err.info());
        return -1;
    } catch (const std::exception& e) {
        log("程序错误: " + std::string(e.what()));
        return -1;
    }
    
    log("GB28181客户端正常退出");
    return 0;
}